﻿using System;
using System.Collections.Generic;
using System.Linq;
using EPiServer;
using EPiServer.Core;
using EPiServer.Filters;
using EPiServer.Framework.Localization;
using EPiServer.Security;
using OpenWaves.EPiServer.Comments.Content.DataMappers;
using OpenWaves.EPiServer.Comments.Models.Pages;
using OpenWaves.EPiServer.Comments.Models.ValueObjects;


namespace OpenWaves.EPiServer.Comments.Content.Repositories
{
    public class EPiServerNavigationTreeCommentsRepository : ICommentsRepository
    {
        private readonly ICommentDataMapper commentDataMapper;
        private Guid givenParentContentGuid;
        private IContentRepository contentRepository;

        protected IContentRepository ContentRepository
        {
            get
            {
                return contentRepository ??
                       (contentRepository =
                        new global::EPiServer.ServiceLocation.ServiceLocationHelper(
                            global::EPiServer.ServiceLocation.ServiceLocator.Current)
                            .ContentRepository());
            }
        }
        

        public EPiServerNavigationTreeCommentsRepository()
        {
            this.commentDataMapper = ServiceLocator.Resolve<ICommentDataMapper>();
        }


        public virtual IEnumerable<Comment> GetCommentsByParentContentGuid(Guid parentContentGuid)
        {
            givenParentContentGuid = parentContentGuid;
            var commentsContainer = GetCommentsContainer();

            if (commentsContainer == null)
                return new List<Comment>();

            var commentsCollection = new PageDataCollection(ContentRepository.GetChildren<CommentPage>(commentsContainer.ContentLink));
            new FilterPublished(PagePublishedStatus.Published).Filter(commentsCollection);
            new FilterAccess(AccessLevel.Read).Filter(commentsCollection);

            var filteredComments = commentsCollection.Cast<CommentPage>()
                .OrderByDescending(c => c.Created)
                .Select(x => commentDataMapper.MapCommentPageToComment(Comment.Create(), x)).ToList();

            return filteredComments;
        }


        public virtual void AddComment(Guid parentContentGuid, Comment comment)
        {
            givenParentContentGuid = parentContentGuid;

            var commentsContainer = GetCommentsContainer() ?? CreateCommentsContainer();

            var commentPage = ContentRepository.GetDefault<CommentPage>(commentsContainer.ContentLink);
            commentPage = commentDataMapper.MapCommentToCommentPage(commentPage, comment);

            ContentRepository.Save(commentPage, global::EPiServer.DataAccess.SaveAction.Publish, global::EPiServer.Security.AccessLevel.NoAccess);
        }


        protected virtual CommentsContainer CreateCommentsContainer()
        {
            var parentPageData = GetPageDataByContentGuid();

            var commentsContainer = ContentRepository.GetDefault<CommentsContainer>(parentPageData.ContentLink);
            commentsContainer.Name = LocalizationService.Current.GetString("/comments/CommentsContainerName", "Comments");

            ContentRepository.Save(commentsContainer, global::EPiServer.DataAccess.SaveAction.Publish, global::EPiServer.Security.AccessLevel.NoAccess);

            return commentsContainer;
        }


        protected virtual CommentsContainer GetCommentsContainer()
        {
            return
                ContentRepository.GetChildren<CommentsContainer>(GetPageDataByContentGuid().ContentLink)
                                 .SingleOrDefault();
        }


        protected virtual PageData GetPageDataByContentGuid()
        {
            return ContentRepository.Get<PageData>(givenParentContentGuid);
        }
    }
}
